home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / net / netRoute.c < prev    next >
C/C++ Source or Header  |  1991-03-16  |  28KB  |  1,012 lines

  1. /* 
  2.  * netRoute.c --
  3.  *
  4.  *    This is the code that maintains a table of routes to
  5.  *    Sprite hosts.  The routes contain the transport level
  6.  *    headers that need to be pre-pended to messages so that
  7.  *    they get to the desired Sprite Host.
  8.  *      Routes are added via a system call or determined dynamically using
  9.  *      Sprite's version of ARP (Address Resolution Protocol).  ARP is
  10.  *      invoked when a call to Net_Output is made with a SpriteID for
  11.  *      which there is no route.  Its use is hidden within Net_Output
  12.  *      should not affect the caller of Net_Output.
  13.  *
  14.  *    Operations on routes are:
  15.  *        Net_InstallRoute - Set the Sprite ID for an ethernet address
  16.  *        Net_AddrToID - Get the Sprite ID for an ethernet address
  17.  *        Net_IDToRoute - Return the route for a Sprite host.
  18.  *    Furthermore, the Test_Stats system call will return a route
  19.  *    to a user program with the NET_GET_ROUTE command.
  20.  *
  21.  * Copyright 1988 Regents of the University of California
  22.  * Permission to use, copy, modify, and distribute this
  23.  * software and its documentation for any purpose and without
  24.  * fee is hereby granted, provided that the above copyright
  25.  * notice appear in all copies.  The University of California
  26.  * makes no representations about the suitability of this
  27.  * software for any purpose.  It is provided "as is" without
  28.  * express or implied warranty.
  29.  *
  30.  */
  31.  
  32. #ifndef lint
  33. static char rcsid[] = "$Header: /sprite/src/kernel/net/RCS/netRoute.c,v 9.8 91/03/15 15:48:23 jhh Exp Locker: mgbaker $ SPRITE (Berkeley)";
  34. #endif
  35.  
  36. #include <sprite.h>
  37. #include <net.h>
  38. #include <netRoute.h>
  39. #include <netInt.h>
  40. #include <netUltraInt.h>
  41. #include <sys.h>
  42. #include <stdlib.h>
  43. #include <timer.h>
  44. #include <sync.h>
  45. #include <proc.h>
  46. #include <rpc.h>
  47. #include <string.h>
  48. #include <vm.h>
  49.  
  50. /*
  51.  * Wildcard address for the Ultranet.  This address matches any address.
  52.  */
  53.  
  54. static Net_UltraTLAddress    wildcardAddress = 
  55.                 {7, NET_ULTRA_TSAP_SIZE};
  56. /*
  57.  * The Route table.
  58.  * The table is indexed by Sprite Host IDs.  Access to
  59.  * the table is synchronized with a MASTER_LOCK to prevent
  60.  * changes from interfering with packet handling.
  61.  */
  62. List_Links    netRouteArray[NET_NUM_SPRITE_HOSTS];
  63. NetHostInfo    netHostInfo[NET_NUM_SPRITE_HOSTS];
  64. int         netNumHosts = NET_NUM_SPRITE_HOSTS;
  65. Sync_Semaphore    netRouteMutex = Sync_SemInitStatic("netRouteMutex");
  66. Sync_Semaphore    netFreeRouteMutex = Sync_SemInitStatic("netFreeRouteMutex");
  67.  
  68. /*
  69.  * Macro to swap the fragOffset field.
  70.  */
  71. #define SWAP_FRAG_OFFSET_HOST_TO_NET(ptr) { \
  72.     unsigned short    *shortPtr; \
  73.     shortPtr = ((unsigned short *)&ptr->ident) + 1; \
  74.     *shortPtr = Net_HostToNetShort(*shortPtr); \
  75.  
  76. static    void        FillRouteInfo _ARGS_((Net_Route *routePtr,
  77.                     Net_RouteInfo *infoPtr));
  78.  
  79.  
  80. /*
  81.  *----------------------------------------------------------------------
  82.  *
  83.  * Net_RouteInit --
  84.  *
  85.  *      Initialize the broadcast routes.  The rest of the routes are
  86.  *      installed via the netRoute user program.  
  87.  *
  88.  *    This uses malloc, so it should be called after Mem_Init.
  89.  *
  90.  * Results:
  91.  *    None.
  92.  *
  93.  * Side effects:
  94.  *    Initialize the route table and add the broadcast route.
  95.  *
  96.  *----------------------------------------------------------------------
  97.  */
  98. void
  99. Net_RouteInit()
  100. {
  101.     register int i;
  102.     int spriteID;
  103.  
  104.     /*
  105.      * The route table.  An array of routes is kept for directing
  106.      * messages to other machines.  It is indexed by Sprite host ids.
  107.      */
  108.     for (spriteID=0 ; spriteID<netNumHosts ; spriteID++) {
  109.     List_Init(&netRouteArray[spriteID]);
  110.     }
  111.     /*
  112.      * Install the broadcast route(s) so we can do our first broadcast rpcs.
  113.      */
  114.     for (i = 0; i < netNumInterfaces;i++) {
  115.     Net_Interface    *interPtr;
  116.     ReturnStatus    status;
  117.  
  118.     interPtr = netInterfaces[i];
  119.     if (interPtr->flags & NET_IFLAGS_BROADCAST) {
  120.         status = Net_InstallRoute(NET_BROADCAST_HOSTID, 
  121.                 interPtr, &interPtr->broadcastAddress, 
  122.                 NET_PROTO_RAW, "broadcast", "unknown", 
  123.                 (ClientData) 0);
  124.         if (status != SUCCESS) {
  125.         printf(
  126.     "Net_RouteInit: unable to install broadcast route for interface %d\n",
  127.             i);
  128.         }
  129.     }
  130.     }
  131.     return;
  132. }
  133.  
  134. /*
  135.  *----------------------------------------------------------------------
  136.  *
  137.  * Net_InstallRouteStub --    
  138.  *
  139.  *    System call stub for Net_InstallRoute
  140.  *
  141.  * Results:
  142.  *    A return status.
  143.  *
  144.  * Side effects:
  145.  *    See Net_InstallRoute
  146.  *
  147.  *----------------------------------------------------------------------
  148.  */
  149. ReturnStatus
  150. Net_InstallRouteStub(size, routeInfoPtr)
  151.     int          size;
  152.     Net_RouteInfo *routeInfoPtr;    /* Route data */
  153. {
  154.     ReturnStatus     status;
  155.     Net_RouteInfo     routeInfo;
  156.     Net_Interface     *interPtr;
  157.  
  158.     if (routeInfoPtr == USER_NIL) {
  159.     return (SYS_ARG_NOACCESS);
  160.     }
  161.     if (size != sizeof(Net_RouteInfo)) {
  162.     return (GEN_INVALID_ARG);
  163.     }
  164.     status = Vm_CopyIn(sizeof(Net_RouteInfo), (Address)routeInfoPtr, 
  165.               (Address)&routeInfo);
  166.     if (status != SUCCESS) {
  167.     return(status);
  168.     }
  169.     if (routeInfo.version != NET_ROUTE_VERSION) {
  170.     return GEN_INVALID_ARG;
  171.     }
  172.     if (routeInfo.interface < 0 || routeInfo.interface >= netNumInterfaces) {
  173.     printf("Net_InstallRouteStub: interface %d does not exist\n",
  174.         routeInfo.interface);
  175.     return(GEN_INVALID_ARG);
  176.     }
  177.     interPtr = Net_GetInterface(routeInfo.netType, routeInfo.interface);
  178.     if (interPtr == (Net_Interface *) NIL) {
  179.     printf("Net_InstallRouteStub: can't find interface %d\n",
  180.         routeInfo.interface);
  181.     return(GEN_INVALID_ARG);
  182.     }
  183.     status = Net_InstallRoute(routeInfo.spriteID,
  184.             interPtr, routeInfo.netAddress, 
  185.             routeInfo.protocol,
  186.             routeInfo.hostname, routeInfo.machType, 
  187.             routeInfo.userData);
  188.     return(status);
  189. }
  190.  
  191. /*
  192.  *----------------------------------------------------------------------
  193.  *
  194.  * Net_InstallRoute --
  195.  *
  196.  *    Install a route to a Sprite host at the specified address.
  197.  *    After installing the route the Sprite ID can be used as an
  198.  *    argument to Rpc_Call to direct an RPC request to that Sprite host.
  199.  *
  200.  * Results:
  201.  *    None.
  202.  *
  203.  * Side effects:
  204.  *    Initialize the entry in the route table which is indexed
  205.  *    by the Sprite ID to point to a route for the Sprite Host.
  206.  *
  207.  *----------------------------------------------------------------------
  208.  */
  209.  
  210. ReturnStatus
  211. Net_InstallRoute(spriteID, interPtr, netAddressPtr, protocol, 
  212.     hostname, machType, clientData)
  213.     int         spriteID;    /* Sprite Host ID */
  214.     Net_Interface    *interPtr;    /* Interface route is for. */
  215.     Net_Address     *netAddressPtr;    /* Network addresses (indexed by
  216.                      * protocol). */
  217.     int            protocol;    /* Protocol to use with route. */
  218.     char         *hostname;    /* Human recognizable name */
  219.     char         *machType;      /* Machine type to expand $MACHINE */
  220.     ClientData        clientData;     /* Data for user-level program. */
  221. {
  222.     register Net_Route     *routePtr;
  223.     Net_Route        *oldRoutePtr;
  224.     ReturnStatus status = SUCCESS;
  225.     char    *headerPtr;
  226.  
  227.     if (Mach_AtInterruptLevel()) {
  228.     printf("Can't install route when at interrupt level (%d)\n",
  229.         spriteID);
  230.     return FAILURE;
  231.     }
  232.     if (spriteID < 0) {
  233.     printf("Invalid sprite id %d\n", spriteID);
  234.     return (GEN_INVALID_ARG);
  235.     }
  236.     /*
  237.      * If we are installing a route and we don't know are own spriteID see
  238.      * if we can learn it from the route.
  239.      */
  240.     if (rpc_SpriteID == 0) {
  241.     if (!NET_ADDRESS_COMPARE(interPtr->netAddress[protocol],
  242.         netAddressPtr[protocol])) {
  243.         rpc_SpriteID = spriteID;
  244.     }
  245.     }
  246.     /*
  247.      * If we know our spriteID and we are installing a route to ourselves we
  248.      * can learn (or at least validate our data).
  249.      */
  250.     if ((rpc_SpriteID > 0) && (rpc_SpriteID == spriteID)) {
  251.     char buffer[128];
  252.  
  253.     if (!(NET_ADDRESS_COMPARE(interPtr->netAddress[protocol],
  254.         netZeroAddress))) {
  255.         interPtr->netAddress[protocol] = netAddressPtr[protocol];
  256.         Net_AddrToString(&interPtr->netAddress[protocol], protocol, 
  257.             interPtr->netType, buffer);
  258.         printf("Setting address to %s\n", buffer);
  259.     } else if (NET_ADDRESS_COMPARE(interPtr->netAddress[protocol], 
  260.             netAddressPtr[protocol])) {
  261.         Net_AddrToString(&interPtr->netAddress[protocol], protocol, 
  262.         interPtr->netType, buffer);
  263.         printf(
  264.         "Warning: address on interface \"%s\" is currently %s\n",
  265.         interPtr->name,
  266.         buffer);
  267.         Net_AddrToString(&netAddressPtr[protocol], protocol, 
  268.         interPtr->netType, buffer);
  269.         printf("Attempt to install route using address %s ignored.\n",
  270.         buffer);
  271.         status = FAILURE;
  272.     }
  273.     return status;
  274.     }
  275.     routePtr = (Net_Route *) malloc(sizeof(Net_Route));
  276.     MASTER_LOCK(&netRouteMutex);
  277.  
  278.     /*
  279.      * In order to install internet routes our internet address must be set.
  280.      */
  281.     if ((protocol == NET_PROTO_INET) && 
  282.     (interPtr->netAddress[protocol].inet == netZeroAddress.inet)) {
  283.  
  284.     Boolean     found = FALSE;
  285.     int        addr;
  286.     Net_Route    *tmpPtr;
  287.     /*
  288.      * Try to do a reverse arp to get the internet address.  
  289.      */
  290.     LIST_FORALL(&netRouteArray[NET_BROADCAST_HOSTID], 
  291.         (List_Links *) tmpPtr){
  292.  
  293.         if (tmpPtr->interPtr == interPtr) {
  294.         found = TRUE;
  295.         break;
  296.         }
  297.     }
  298.     if (!found) {
  299.         printf("Can't find broadcast route for interface %s\n",
  300.         interPtr->name);
  301.         MASTER_UNLOCK(&netRouteMutex);
  302.         return FAILURE;
  303.     }
  304.     addr = Net_RevArp(tmpPtr, protocol, (Net_Address *) NIL, 
  305.             &netRouteMutex);
  306.     if (addr == -1) {
  307.         printf("Internet address for interface \"%s\" is not set and\n",
  308.         interPtr->name);
  309.         printf("reverse arp failed.  Can't install route.\n");
  310.         MASTER_UNLOCK(&netRouteMutex);
  311.         return FAILURE;
  312.     }
  313.     interPtr->netAddress[protocol].inet = addr;
  314.     }
  315.     if (spriteID >= NET_NUM_SPRITE_HOSTS) {
  316.     printf("Net route table too small!\n");
  317.     MASTER_UNLOCK(&netRouteMutex);
  318.     return FAILURE;
  319.     } else {
  320.     Net_Route     *tmpPtr;
  321.     oldRoutePtr = (Net_Route *)NIL;
  322.     LIST_FORALL(&netRouteArray[spriteID], (List_Links *) tmpPtr) {
  323.         if ((tmpPtr->interPtr == interPtr) &&
  324.         (tmpPtr->protocol == protocol)) {
  325.  
  326.         tmpPtr->flags &= ~NET_RFLAGS_VALID;
  327.         oldRoutePtr = tmpPtr;
  328.         break;
  329.         }
  330.     }
  331.     List_InitElement((List_Links *) routePtr);
  332.     List_Insert((List_Links *) routePtr, 
  333.         LIST_ATREAR((List_Links *) &netRouteArray[spriteID]));
  334.     (void) strncpy(netHostInfo[spriteID].name, hostname, 20);
  335.     (void) strncpy(netHostInfo[spriteID].machType, machType, 12);
  336.  
  337.     routePtr->flags = NET_RFLAGS_VALID;
  338.     routePtr->refCount = 0;
  339.     routePtr->spriteID = spriteID;
  340.     routePtr->interPtr = interPtr;
  341.     routePtr->maxBytes = interPtr->maxBytes;
  342.     routePtr->minBytes = interPtr->minBytes;
  343.     routePtr->protocol = protocol;
  344.     routePtr->routeID |= spriteID << 16;
  345.     routePtr->userData = clientData;
  346.     sprintf(routePtr->desc, "Route to %s - ", hostname);
  347.     }
  348.     /*
  349.      * Prepare the Route.  This includes the transport header that
  350.      * will be used in messages sent to the Sprite Host.
  351.      */
  352.     headerPtr = (char *) routePtr->buffer;
  353.     switch(interPtr->netType) {
  354.     case NET_NETWORK_ETHER: {
  355.         Net_EtherHdr *etherHdrPtr;
  356.         strcat(routePtr->desc, "ethernet, ");
  357.         /*
  358.          * Fill in an ethernet header for the route.
  359.          * The drivers fill in the source part of the ethernet header 
  360.          * each time they send out a packet.
  361.          */
  362.         if (oldRoutePtr != (Net_Route *) NIL) {
  363.         etherHdrPtr = (Net_EtherHdr *)oldRoutePtr->headerPtr;
  364.         if (NET_ETHER_COMPARE(
  365.             NET_ETHER_HDR_DESTINATION(*etherHdrPtr),
  366.             netAddressPtr[NET_PROTO_RAW].ether)) {
  367.             printf(
  368.         "Warning: Net_InstallRoute, host <%d> changing ethernet addr\n",
  369.                 spriteID);
  370.         }
  371.         }
  372.         if (protocol == NET_PROTO_RAW) {
  373.         etherHdrPtr = (Net_EtherHdr *)routePtr->buffer;
  374.         NET_ETHER_HDR_TYPE(*etherHdrPtr) = 
  375.             Net_HostToNetShort(NET_ETHER_SPRITE);
  376.         } else {
  377.         /*
  378.          * Make the ethernet header start on an odd 16 bit boundary so
  379.          * that the (internet) header that follows starts on a
  380.          * 32 bit boundary.
  381.          */
  382.         etherHdrPtr = (Net_EtherHdr *)
  383.             ((((int) routePtr->buffer + 5) & ~0x3) - 2);
  384.         NET_ETHER_HDR_TYPE(*etherHdrPtr) = 
  385.                     Net_HostToNetShort(NET_ETHER_IP);
  386.         }
  387.         routePtr->headerPtr[NET_PROTO_RAW] = (Address)etherHdrPtr;
  388.         NET_ETHER_ADDR_COPY(netAddressPtr[NET_PROTO_RAW].ether,
  389.                 NET_ETHER_HDR_DESTINATION(*etherHdrPtr));
  390.         NET_ETHER_ADDR_COPY(interPtr->netAddress[NET_PROTO_RAW].ether,
  391.                 NET_ETHER_HDR_SOURCE(*etherHdrPtr));
  392.         routePtr->netAddress[NET_PROTO_RAW].ether = 
  393.         netAddressPtr[NET_PROTO_RAW].ether;
  394.         headerPtr = (char *) etherHdrPtr;
  395.         break;
  396.     }
  397.     case NET_NETWORK_ULTRA: {
  398.         Net_UltraHeader    *ultraHdrPtr;
  399.  
  400.         ultraHdrPtr = (Net_UltraHeader *) routePtr->buffer;
  401.         bzero((char *) ultraHdrPtr, sizeof(Net_UltraHeader));
  402.         strcat(routePtr->desc, "ultranet, ");
  403.         routePtr->headerPtr[NET_PROTO_RAW] = (Address) ultraHdrPtr;
  404.         ultraHdrPtr->remoteAddress = wildcardAddress;
  405.         ultraHdrPtr->remoteAddress.tsapSize=2;
  406.         ultraHdrPtr->remoteAddress.tsap[0]=0xff;
  407.         ultraHdrPtr->remoteAddress.tsap[1]=0xff;
  408.         ultraHdrPtr->remoteAddress.address = 
  409.         netAddressPtr[NET_PROTO_RAW].ultra;
  410.         ultraHdrPtr->localAddress = wildcardAddress;
  411.         ultraHdrPtr->localAddress.tsapSize=2;
  412.         ultraHdrPtr->localAddress.tsap[0]=0xff;
  413.         ultraHdrPtr->localAddress.tsap[1]=0xff;
  414.         ultraHdrPtr->localAddress.address = 
  415.         interPtr->netAddress[NET_PROTO_RAW].ultra;
  416.         ultraHdrPtr->cmd = NET_ULTRA_DGRAM_SEND_REQ;
  417.         headerPtr = (char *) ultraHdrPtr;
  418.         routePtr->netAddress[NET_PROTO_RAW].ultra = 
  419.         netAddressPtr[NET_PROTO_RAW].ultra;
  420.         break;
  421.     }
  422.     default:
  423.         printf("Net_InstallRoute: Unknown interface type %d\n", 
  424.         interPtr->netType);
  425.         return FAILURE;
  426.     }
  427.     headerPtr += net_NetworkHeaderSize[interPtr->netType];
  428.     switch (protocol) {
  429.     case NET_PROTO_RAW:
  430.         strcat(routePtr->desc, "raw");
  431.         break;
  432.     case NET_PROTO_INET: {
  433.         Net_IPHeader *ipHeader;
  434.         strcat(routePtr->desc, "IP");
  435.         ipHeader = (Net_IPHeader *) headerPtr;
  436.         routePtr->headerPtr[protocol] = (Address)ipHeader;
  437.         /*
  438.          * Initialize the template ipHeader.
  439.          */
  440.         bzero((char *)ipHeader, sizeof(Net_IPHeader));
  441.         ipHeader->headerLen = sizeof(Net_IPHeader) / 4;
  442.         ipHeader->version = NET_IP_VERSION;
  443.         ipHeader->typeOfService = 0;
  444.         /*
  445.          * Kernel IP doesn't handle fragmented IP packets (yet).
  446.          */
  447.         ipHeader->flags = NET_IP_DONT_FRAG;
  448.         SWAP_FRAG_OFFSET_HOST_TO_NET(ipHeader);
  449.         ipHeader->timeToLive = NET_IP_MAX_TTL;
  450.         ipHeader->protocol = NET_IP_PROTOCOL_SPRITE;
  451.         ipHeader->source = interPtr->netAddress[protocol].inet;
  452.         ipHeader->dest = netAddressPtr[NET_PROTO_INET].inet;
  453.         /*
  454.          * Precompute the checksum for the ipHeader. This must be
  455.          * corrected when the totalLen field is updated. Note we
  456.          * store the checksum as the 16 bit sum of the packet
  457.          * header to permit easy updating.
  458.          */
  459.         ipHeader->checksum = Net_InetChecksum(sizeof(Net_IPHeader),
  460.                            (Address) ipHeader);
  461.         ipHeader->checksum = ~ipHeader->checksum;
  462.         routePtr->maxBytes -= sizeof(Net_IPHeader);
  463.         routePtr->minBytes -= sizeof(Net_IPHeader);
  464.         if (routePtr->minBytes < 0) {
  465.         routePtr->minBytes = 0;
  466.         }
  467.         routePtr->netAddress[NET_PROTO_INET].inet = 
  468.         netAddressPtr[NET_PROTO_INET].inet;
  469.         break;
  470.     }
  471.     default: {
  472.         if (oldRoutePtr != (Net_Route *) NIL) {
  473.         oldRoutePtr->flags |= NET_RFLAGS_VALID;
  474.         }
  475.         routePtr->flags &= ~NET_RFLAGS_VALID;
  476.         oldRoutePtr = routePtr;
  477.         printf("Warning: Unsupported route type in Net_InstallRoute\n");
  478.         break;
  479.     }
  480.     }
  481.     MASTER_UNLOCK(&netRouteMutex);
  482.     if (oldRoutePtr != (Net_Route *) NIL) {
  483.     Net_DeleteRoute(oldRoutePtr);
  484.     }
  485.     return(SUCCESS);
  486. }
  487.  
  488. /*
  489.  *----------------------------------------------------------------------
  490.  *
  491.  * Net_ReleaseRoute --
  492.  *
  493.  *    Releases a route by decrementing its reference count.
  494.  *
  495.  * Results:
  496.  *    None.
  497.  *
  498.  * Side effects:
  499.  *    The route if freed if it is invalid and the reference count is zero.
  500.  *
  501.  *----------------------------------------------------------------------
  502.  */
  503.  
  504. void
  505. Net_ReleaseRoute(routePtr)
  506.     Net_Route     *routePtr;
  507. {
  508.     Boolean     freeIt = FALSE;
  509.     MASTER_LOCK(&netRouteMutex);
  510.     routePtr->refCount--;
  511.     if (Mach_AtInterruptLevel()) {
  512.     goto exit;
  513.     }
  514.     if ((!(routePtr->flags & NET_RFLAGS_VALID)) && 
  515.     (routePtr->refCount <= 0) &&
  516.     (!(routePtr->flags & NET_RFLAGS_DELETING))) {
  517.     routePtr->flags |= NET_RFLAGS_DELETING;
  518.     freeIt = TRUE;
  519.     }
  520. exit:
  521.     MASTER_UNLOCK(&netRouteMutex);
  522.     if (freeIt) {
  523.     List_Remove((List_Links *) routePtr);
  524.     free((char *) routePtr);
  525.     }
  526. }
  527.  
  528. /*
  529.  *----------------------------------------------------------------------
  530.  *
  531.  * Net_DeleteRoute --
  532.  *
  533.  *    Deletes a route.
  534.  *
  535.  * Results:
  536.  *    None.
  537.  *
  538.  * Side effects:
  539.  *    The route is marked as invalid if it has a positive reference
  540.  *    count, otherwise it is deleted.
  541.  *
  542.  *----------------------------------------------------------------------
  543.  */
  544.  
  545. void
  546. Net_DeleteRoute(routePtr)
  547.     Net_Route    *routePtr;
  548. {
  549.     Boolean     freeIt = FALSE;
  550.     MASTER_LOCK(&netRouteMutex);
  551.     routePtr->flags &= ~NET_RFLAGS_VALID;
  552.     if (Mach_AtInterruptLevel()) {
  553.     goto exit;
  554.     }
  555.     if ((routePtr->refCount <= 0) && 
  556.     (!(routePtr->flags & NET_RFLAGS_DELETING))) {
  557.     routePtr->flags |= NET_RFLAGS_DELETING;
  558.     freeIt = TRUE;
  559.     }
  560. exit:
  561.     MASTER_UNLOCK(&netRouteMutex);
  562.     if (freeIt) {
  563.     List_Remove((List_Links *) routePtr);
  564.     free((char *) routePtr);
  565.     }
  566. }
  567.  
  568. /*
  569.  *----------------------------------------------------------------------
  570.  *
  571.  * Net_IDToRouteStub --
  572.  *
  573.  *    Stub for the Test_Stats system call, NET_GET_ROUTE command.
  574.  *    This gets a route and copies it out to user space.
  575.  *
  576.  * Results:
  577.  *    A return status.
  578.  *
  579.  * Side effects:
  580.  *    Copies to user space.
  581.  *
  582.  *----------------------------------------------------------------------
  583.  */
  584. ReturnStatus
  585. Net_IDToRouteStub(spriteID, size, argPtr)
  586.     int spriteID;        /* option parameter to Test_Stats */
  587.     int    size;            /* Size of user buffer. */
  588.     Address argPtr;        /* User space buffer to hold route */
  589.  
  590. {
  591. #define MIN(a,b) ((a) < (b) ? (a) : (b))
  592.  
  593.     ReturnStatus status;
  594.     Net_Route *routePtr;
  595.     Net_RouteInfo routeInfo;
  596.     int toCopy;
  597.  
  598.     if (spriteID < 0 || spriteID >= netNumHosts) {
  599.     return(SYS_INVALID_ARG);
  600.     }
  601.     routePtr = Net_IDToRoute(spriteID, 0, FALSE, (Sync_Semaphore *) NIL, 0);
  602.     if (routePtr == (Net_Route *)NIL) {
  603.     routeInfo.version = NET_ROUTE_VERSION;
  604.     routeInfo.flags = 0;
  605.     } else {
  606.     FillRouteInfo(routePtr, &routeInfo);
  607.     }
  608.     toCopy = MIN(size, sizeof(Net_RouteInfo) - sizeof(Net_Header));
  609.     status = Vm_CopyOut(toCopy, (Address)&routeInfo, argPtr);
  610.     if (routePtr == (Net_Route *) NIL) {
  611.     return status;
  612.     }
  613.     if (status == SUCCESS) {
  614.     argPtr += toCopy;
  615.     size -= toCopy;
  616.     toCopy = MIN(size, net_NetworkHeaderSize[routePtr->interPtr->netType]);
  617.     status = Vm_CopyOut(toCopy, 
  618.             (Address)routePtr->headerPtr[NET_PROTO_RAW], 
  619.             argPtr);
  620.     argPtr += toCopy;
  621.     size -= toCopy;
  622.     switch(routePtr->protocol) {
  623.         case NET_PROTO_INET:
  624.         toCopy = MIN(size, sizeof(Net_IPHeader));
  625.         status = Vm_CopyOut(sizeof(Net_IPHeader), 
  626.                  (Address)routePtr->headerPtr[NET_PROTO_INET],
  627.                  argPtr);
  628.         argPtr += toCopy;
  629.         size -= toCopy;
  630.         break;
  631.         default:
  632.         break;
  633.     }
  634.     }
  635.     Net_ReleaseRoute(routePtr);
  636.     return(status);
  637. }
  638.  
  639. /*
  640.  *----------------------------------------------------------------------
  641.  *
  642.  * Net_IDToRoute --
  643.  *
  644.  *    Return the route to the host specified by the input sprite id.
  645.  *
  646.  * Results:
  647.  *    A pointer to the route for the host.
  648.  *
  649.  * Side effects:
  650.  *    None.
  651.  *
  652.  *----------------------------------------------------------------------
  653.  */
  654. /*ARGSUSED*/
  655. Net_Route *
  656. Net_IDToRoute(spriteID, index, doArp, mutexPtr, size)
  657.     int     spriteID;    /* Sprite id to find route for. */
  658.     int     index;        /* Which route of many. */
  659.     Boolean    doArp;        /* Do an arp to find a route? */
  660.     Sync_Semaphore *mutexPtr;    /* Mutex to release when doing arp. */
  661.     int     size;        /* Size of data to send (not used yet). */
  662. {
  663.     Net_Route     *routePtr = (Net_Route *) NIL;
  664.     register    Net_Route *tmpPtr;
  665.     int            i;
  666.     ReturnStatus    status;
  667.  
  668.     if (spriteID >= 0 && spriteID < netNumHosts) {
  669.     while (1) {
  670.         i = 0;
  671.         MASTER_LOCK(&netRouteMutex);
  672.         LIST_FORALL(&netRouteArray[spriteID],(List_Links *) tmpPtr) {
  673.         if (tmpPtr->flags & NET_RFLAGS_VALID) {
  674.             if (index >= 0 && i == index) {
  675.             tmpPtr->refCount++;
  676.             routePtr = tmpPtr;
  677.             break;
  678.             } 
  679.             i++;
  680.         }
  681.         }
  682.         MASTER_UNLOCK(&netRouteMutex);
  683.         if (routePtr == (Net_Route *) NIL && doArp) {
  684.         status = Net_Arp(spriteID, mutexPtr);
  685.         if (status != SUCCESS) {
  686.             break;
  687.         }
  688.         doArp = FALSE;
  689.         } else {
  690.         break;
  691.         }
  692.     }
  693.     }
  694.     return(routePtr);
  695. }
  696.  
  697. /*
  698.  *----------------------------------------------------------------------
  699.  *
  700.  * Net_AddrToID --
  701.  *
  702.  *      Determine the Sprite host ID from a physical address.  This is
  703.  *      used by a server, or Reverse Arp, to determine a client's Sprite
  704.  *      ID from the client's network address.
  705.  *
  706.  *      This routine scans the route table looking for an address
  707.  *      match with the input address.  
  708.  *
  709.  * Results:
  710.  *      A Sprite hostid for the host at the address.  If the physical
  711.  *      address isn't in the table we return a hostid of -1.
  712.  *
  713.  * Side effects:
  714.  *    None.
  715.  *
  716.  *----------------------------------------------------------------------
  717.  */
  718. int
  719. Net_AddrToID(netType, protocol, addressPtr)
  720.     Net_NetworkType netType;
  721.     int        protocol;
  722.     Net_Address    *addressPtr;        /* Physical address */
  723. {
  724.     register Net_Route     *routePtr;
  725.     register int     i;
  726.     register int     ID = -1;
  727.  
  728.     MASTER_LOCK(&netRouteMutex);
  729.  
  730.     for (i=0 ; i<netNumHosts ; i++) {
  731.     LIST_FORALL(&netRouteArray[i],(List_Links *) routePtr) {
  732.         if ((routePtr->protocol == protocol) &&
  733.         (routePtr->interPtr->netType == netType) &&
  734.         (!NET_ADDRESS_COMPARE(routePtr->netAddress[protocol], 
  735.             *addressPtr))) {
  736.         ID = routePtr->spriteID;
  737.         break;
  738.         }
  739.     }
  740.     }
  741.     MASTER_UNLOCK(&netRouteMutex);
  742.     return(ID);
  743. }
  744.  
  745. /*
  746.  *----------------------------------------------------------------------
  747.  *
  748.  * Net_HdrToID --
  749.  *
  750.  *      Determine the Sprite host ID from a transport header.  This is
  751.  *      used by a server to determine a client's Sprite
  752.  *      ID from the transport header.
  753.  *
  754.  *      This routine scans the route table looking for an address
  755.  *      match with the input address.  If the flags field of the route
  756.  *      specifies that the address is a broadcast address, this will
  757.  *      return the correct hostid to use for a broadcast.
  758.  *
  759.  * Results:
  760.  *      A Sprite hostid for the host at the address.  If the physical
  761.  *      address isn't in the table we return a hostid of -1.
  762.  *
  763.  * Side effects:
  764.  *    None.
  765.  *
  766.  *----------------------------------------------------------------------
  767.  */
  768. int
  769. Net_HdrToID(netType, protocol, headerPtr)
  770.     Net_NetworkType    netType;
  771.     int            protocol;
  772.     Address headerPtr;    /* Transport header. */
  773. {
  774.     Address         offsetPtr;
  775.     Net_Address     netAddress;
  776.  
  777.     bzero((char *) &netAddress, sizeof(Net_Address));
  778.     if (protocol == NET_PROTO_RAW) {
  779.     switch(netType) {
  780.         case NET_NETWORK_ETHER: {
  781.         NET_ETHER_ADDR_COPY(
  782.             NET_ETHER_HDR_SOURCE(*((Net_EtherHdr *) headerPtr)), 
  783.             netAddress.ether);
  784.         break;
  785.         }
  786.         case NET_NETWORK_ULTRA: {
  787.         netAddress.ultra = 
  788.             ((Net_UltraHeader *) headerPtr)->remoteAddress.address;
  789.         break;
  790.         }
  791.         default:
  792.         printf("Net_HdrToID: unknown netType %d\n", netType);
  793.         return -1;
  794.     }
  795.     } else {
  796.     offsetPtr = headerPtr + net_NetworkHeaderSize[netType];
  797.     switch(protocol) {
  798.         case NET_PROTO_INET : {
  799.         netAddress.inet = 
  800.             Net_NetToHostInt(((Net_IPHeader *) offsetPtr)->dest);
  801.         break;
  802.         }
  803.         default:
  804.         printf("Net_HdrToID: unknown protocol %d\n", protocol);
  805.         return -1;
  806.     }
  807.     }
  808.     return Net_AddrToID(netType, protocol, &netAddress);
  809. }
  810.  
  811.  
  812. /*
  813.  *----------------------------------------------------------------------
  814.  *
  815.  * Net_HdrDestString --
  816.  *
  817.  *    Build a printable message of the destination address from a 
  818.  *    transport header.
  819.  *
  820.  *
  821.  * Results:
  822.  *    None.
  823.  *
  824.  * Side effects:
  825.  *    None.
  826.  *
  827.  *----------------------------------------------------------------------
  828.  */
  829. void
  830. Net_HdrDestString(netType, protocol, headerPtr, bufferLen, buffer)
  831.     Net_NetworkType    netType;
  832.     int            protocol;
  833.     Address headerPtr;    /* Transport header. */
  834.     int    bufferLen;    /* Length of buffer. */
  835.     char *buffer;    /* Destination memory for destination string. */
  836.  
  837. {
  838.     Address         offsetPtr;
  839.     Net_Address     netAddress;
  840.     static char        tmpBuffer[128];
  841.  
  842.     *buffer = '\0';
  843.     if (protocol == NET_PROTO_RAW) {
  844.     switch(netType) {
  845.         case NET_NETWORK_ETHER: {
  846.         NET_ETHER_ADDR_COPY(
  847.             NET_ETHER_HDR_SOURCE(*((Net_EtherHdr *) headerPtr)), 
  848.             netAddress.ether);
  849.         break;
  850.         }
  851.         case NET_NETWORK_ULTRA: {
  852.         netAddress.ultra = 
  853.             ((Net_UltraHeader *) headerPtr)->remoteAddress.address;
  854.         break;
  855.         }
  856.         default:
  857.         printf("Net_HdrDestString: unknown netType %d\n", netType);
  858.         return;
  859.     }
  860.     } else {
  861.     offsetPtr = headerPtr + net_NetworkHeaderSize[netType];
  862.     switch(protocol) {
  863.         case NET_PROTO_INET : {
  864.         netAddress.inet = 
  865.             Net_NetToHostInt(((Net_IPHeader *) offsetPtr)->dest);
  866.         break;
  867.         }
  868.         default:
  869.         printf("Net_HdrDestString: unknown protocol %d\n", protocol);
  870.         return;
  871.     }
  872.     }
  873.     Net_AddrToString(&netAddress, netType, protocol, tmpBuffer);
  874.     (void) strncpy(buffer, tmpBuffer, bufferLen-1);
  875.     return;
  876. }
  877.  
  878.  
  879. /*
  880.  *----------------------------------------------------------------------------
  881.  *
  882.  * Net_SpriteIDToName --
  883.  *
  884.  *    Map from a Sprite ID to a host name.
  885.  *
  886.  * Results:
  887.  *      None.
  888.  *
  889.  * Side effects:
  890.  *      None.
  891.  *
  892.  *----------------------------------------------------------------------------
  893.  */
  894.  
  895. void
  896. Net_SpriteIDToName(spriteID, bufferLen, buffer)
  897.     int     spriteID;
  898.     int        bufferLen;
  899.     char     *buffer;
  900. {
  901.     *buffer = '\0';
  902.     MASTER_LOCK(&netRouteMutex);
  903.     if (spriteID >= 0 && spriteID < netNumHosts) {
  904.     (void) strncpy(buffer, netHostInfo[spriteID].name, bufferLen-1);
  905.     }
  906.     MASTER_UNLOCK(&netRouteMutex);
  907.     return;
  908. }
  909.  
  910. /*
  911.  *----------------------------------------------------------------------------
  912.  *
  913.  * Net_SpriteIDToMachType --
  914.  *
  915.  *    Map from a Sprite ID to a machine type string.  This string is
  916.  *    used by the filesystem when expanding $MACHINE in pathnames.
  917.  *
  918.  * Results:
  919.  *      A pointer to a string identifying the machine type, i.e. "sun3".
  920.  *
  921.  * Side effects:
  922.  *      None.
  923.  *
  924.  *----------------------------------------------------------------------------
  925.  */
  926.  
  927. void
  928. Net_SpriteIDToMachType(spriteID, bufferLen, buffer)
  929.     int     spriteID;
  930.     int        bufferLen;
  931.     char    *buffer;
  932. {
  933.     *buffer = '\0';
  934.     MASTER_LOCK(&netRouteMutex);
  935.     if (spriteID >= 0 && spriteID < netNumHosts) {
  936.     (void) strncpy(buffer, netHostInfo[spriteID].machType, bufferLen-1);
  937.     }
  938.     MASTER_UNLOCK(&netRouteMutex);
  939.     return;
  940. }
  941.  
  942. /*
  943.  *----------------------------------------------------------------------
  944.  *
  945.  * Net_HostPrint --
  946.  *
  947.  *    Print out a statement concerning a host.  This maps to a
  948.  *    string hostname if possible, and prints out the message.
  949.  *
  950.  * Results:
  951.  *    None.
  952.  *
  953.  * Side effects:
  954.  *    printf.
  955.  *
  956.  *----------------------------------------------------------------------
  957.  */
  958.  
  959. void
  960. Net_HostPrint(spriteID, string)
  961.     int spriteID;
  962.     char *string;
  963. {
  964.     Sys_HostPrint(spriteID, string);
  965.     return;
  966. }
  967.  
  968. /*
  969.  *----------------------------------------------------------------------
  970.  *
  971.  * FillRouteInfo --
  972.  *
  973.  *    Converts from a Net_Route to a Net_RouteInfo. Net_RouteInfo
  974.  *     is the structure that is passed to user-level.
  975.  *
  976.  * Results:
  977.  *    None.
  978.  *
  979.  * Side effects:
  980.  *    None.
  981.  *
  982.  *----------------------------------------------------------------------
  983.  */
  984.  
  985. static void
  986. FillRouteInfo(routePtr, infoPtr)
  987.     Net_Route        *routePtr;     /* The route structure. */
  988.     Net_RouteInfo    *infoPtr;    /* The route info structure. */
  989. {
  990.     int        i;
  991.  
  992.     infoPtr->version = NET_ROUTE_VERSION;
  993.     infoPtr->spriteID = routePtr->spriteID;
  994.     infoPtr->protocol = routePtr->protocol;
  995.     infoPtr->interface = routePtr->interPtr->number;
  996.     infoPtr->netType = routePtr->interPtr->netType;
  997.     infoPtr->refCount = routePtr->refCount;
  998.     infoPtr->routeID = routePtr->routeID;
  999.     infoPtr->flags = routePtr->flags;
  1000.     infoPtr->maxBytes = routePtr->maxBytes;
  1001.     infoPtr->minBytes = routePtr->minBytes;
  1002.     infoPtr->userData = routePtr->userData;
  1003.     for(i = 0; i < NET_MAX_PROTOCOLS; i++) {
  1004.     infoPtr->netAddress[i] = routePtr->netAddress[i];
  1005.     }
  1006.     strncpy(infoPtr->hostname, netHostInfo[routePtr->spriteID].name, 20);
  1007.     strncpy(infoPtr->machType, netHostInfo[routePtr->spriteID].machType, 12);
  1008.     strncpy(infoPtr->desc, routePtr->desc, 64);
  1009. }
  1010.  
  1011.